﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections.Specialized;
using System.IO;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.IO.Compression;

namespace _12306helper.Common.Net
{
    public class HttpClient
    {
        private string UA = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0";
        private string ContentType = "application/x-www-form-urlencoded";
        private CookieContainer cookies = null;
        private int Timeout = 30000;
        private Encoding encode = Encoding.UTF8;
        private string Host = "kyfw.12306.cn";
        public HttpClient(CookieContainer cookies)
        {
            this.cookies = cookies;
        }
        public string Get(string url, string host, string referer)
        {
            return getRespString(url, "", CommonUtil.HttpMethodGet, host, referer);
        }
        public string Post(string url, string data, string host, string referer)
        {
            return getRespString(url, data, CommonUtil.HttpMethodPost, host, referer);
        }
        public byte[] GetImageBytes(string url, string host, string referer)
        {
            byte[] result = null;
            HttpWebResponse resp = getResp(url, "", CommonUtil.HttpMethodGet, host, referer);
            using (Stream respStream = resp.GetResponseStream())
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    byte[] array = new byte[4096];
                    int count = 0;
                    while ((count = respStream.Read(array, 0, array.Length)) > 0)
                    {
                        memoryStream.Write(array, 0, array.Length);
                    }
                    result = memoryStream.GetBuffer();
                }
            }
            return result;
        }
        public Stream GetImageStream(string url, string host, string referer)
        {
            HttpWebResponse resp = getResp(url, "", CommonUtil.HttpMethodGet, host, referer);
            return resp.GetResponseStream();
        }
        public string createParameter(IDictionary<string, string> param)
        {
            if (param == null) return "";
            StringBuilder result = new StringBuilder();
            foreach (string k in param.Keys)
            {
                result.AppendFormat("&{0}={1}", k, param[k]);
            }
            return result.ToString().Substring(1);
        }
        private string getRespString(string url, string data, string method, string host, string referer)
        {
            string result = string.Empty;
            HttpWebResponse resp = getResp(url, data, method, host, referer);
            if (resp != null)
            {
                Stream stream = resp.GetResponseStream();
                if (resp.ContentEncoding.ToLower().Contains("gzip"))
                {
                    stream = new GZipStream(stream, CompressionMode.Decompress);
                }
                using (StreamReader streamReader = new StreamReader(stream, this.encode))
                {
                    result = streamReader.ReadToEnd();
                }

            }
            return result;
        }
        private HttpWebResponse getResp(string url, string data, string method, string host, string referer)
        {
            HttpWebResponse resp = null;
            try
            {
                HttpWebRequest req = HttpWebRequest.Create(url) as HttpWebRequest;
                req.AllowAutoRedirect = true;
                req.ContentType = this.ContentType;
                req.CookieContainer = this.cookies;
                if (string.IsNullOrEmpty(host))
                {
                    req.Host = this.Host;
                }
                else
                {
                    req.Host = host;
                }

                req.KeepAlive = true;
                req.Method = method.ToUpper();
                req.Referer = referer;
                req.Timeout = this.Timeout;
                req.UserAgent = this.UA;
                req.ContentLength = 0;
                NameValueCollection coll = new NameValueCollection();
                coll.Add("Accept-Encoding", "gzip,deflate,sdch");
                coll.Add("Accept-Language", "zh-CN,zh;q=0.8");
                coll.Add("X-Requested-With", "XMLHttpRequest");
                req.Headers.Add(coll);
                if (!string.IsNullOrEmpty(data))
                {
                    byte[] enData = encode.GetBytes(data);
                    req.ContentLength = enData.Length;
                    Stream reqStream = req.GetRequestStream();
                    reqStream.Write(enData, 0, enData.Length);
                    reqStream.Close();
                }
                if (url.StartsWith("https"))
                {
                    ServicePointManager.ServerCertificateValidationCallback = (RemoteCertificateValidationCallback)Delegate.Combine(ServicePointManager.ServerCertificateValidationCallback, new RemoteCertificateValidationCallback(ValidateServerCertificate));
                }
                resp = req.GetResponse() as HttpWebResponse;
                if (resp != null)
                {
                    if (resp.Cookies.Count > 0)
                    {
                        this.cookies.Add(resp.Cookies);
                    }
                }
            }
            catch (Exception)
            {
                resp = null;
            }
            return resp;
        }
        private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
    }
}
